package com.tarena.lbs.content.dao.repository.impl;

import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import co.elastic.clients.json.JsonData;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.content.dao.repository.ArticleESRepository;
import com.tarena.lbs.content.dao.repository.ArticleRepository;
import com.tarena.lbs.content.pojo.param.ArticleContentParam;
import com.tarena.lbs.content.pojo.po.ActionSearchPO;
import com.tarena.lbs.content.pojo.po.ArticleSearchPO;
import com.tarena.lbs.content.pojo.query.ArticleQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class ArticleRepositoryImpl implements ArticleRepository{
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Override
    public PageInfo<ArticleSearchPO> pageList(ArticleQuery articleQuery) {
        log.info("ES分页查询文章列表:{}, 页码:{}, 每页大小:{}", articleQuery, articleQuery.getPageNo(), articleQuery.getPageSize());

        // 构建查询条件
        BoolQuery.Builder boolQuery = QueryBuilders.bool();

        // 添加查询条件
        if (articleQuery.getArticleTitle() != null && !articleQuery.getArticleTitle().isEmpty()) {
            boolQuery.must(QueryBuilders.match(t -> t.field("articleTitle").query(articleQuery.getArticleTitle())));
        }

        if (articleQuery.getArticleCategoryId() != null) {
            boolQuery.must(QueryBuilders.term(t -> t.field("articleCategoryId").value(articleQuery.getArticleCategoryId())));
        }

        if (articleQuery.getArticleLabel() != null && !articleQuery.getArticleLabel().isEmpty()) {
            boolQuery.must(QueryBuilders.term(t -> t.field("articleLabel").value(articleQuery.getArticleLabel())));
        }

        if (articleQuery.getArticleStatus() != null && !articleQuery.getArticleStatus().isEmpty()) {
            // 使用正确的方式构建terms查询
            BoolQuery.Builder statusBool = QueryBuilders.bool();
            for (Integer status : articleQuery.getArticleStatus()) {
                statusBool.should(QueryBuilders.term(t -> t.field("articleStatus").value(status)));
            }
            boolQuery.must(statusBool.build()._toQuery());
        }

        /*if (articleQuery.getSource() != null) {
            boolQuery.must(QueryBuilders.term(t -> t.field("source").value(articleQuery.getSource())));
        }*/

        if (articleQuery.getActivityId() != null) {
            boolQuery.must(QueryBuilders.term(t -> t.field("activityId").value(articleQuery.getActivityId())));
        }

        if (articleQuery.getUserId() != null) {
            boolQuery.must(QueryBuilders.term(t -> t.field("userId").value(articleQuery.getUserId())));
        }

        // 时间范围查询 - 使用日期字符串格式
        if (articleQuery.getUpdateStartTime() != null) {
            boolQuery.must(QueryBuilders.range().field("updateTime").gte(JsonData.of(articleQuery.getUpdateStartTime())).build()._toQuery());
        }

        if (articleQuery.getUpdateEndTime() != null) {
            boolQuery.must(QueryBuilders.range().field("updateTime").lte(JsonData.of(articleQuery.getUpdateEndTime())).build()._toQuery());
        }
        // 构建NativeQuery
        NativeQuery nativeQuery = NativeQuery.builder()
                .withQuery(boolQuery.build()._toQuery())
                .withPageable(PageRequest.of(articleQuery.getPageNo() - 1, articleQuery.getPageSize()))
                .withSort(Sort.by(Sort.Order.desc("updateTime")))
                .build();

        // 执行ES查询
        SearchHits<ArticleSearchPO> searchHits = elasticsearchTemplate.search(nativeQuery, ArticleSearchPO.class);

        // 转换结果
        List<ArticleSearchPO> articleList = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        log.info("ES查询结果:{}", articleList);
        // 构建PageInfo对象
        PageInfo<ArticleSearchPO> pageInfo = new PageInfo<>();
        pageInfo.setList(articleList);
        pageInfo.setPageNum(articleQuery.getPageNo());
        pageInfo.setPageSize(articleQuery.getPageSize());
        pageInfo.setTotal(searchHits.getTotalHits());
        pageInfo.setPages((int) Math.ceil((double) searchHits.getTotalHits() / articleQuery.getPageSize()));

        return pageInfo;
    }

    @Override
    public PageInfo<ArticleSearchPO> getArticlesByUserBehavior(Integer userId, Integer behaviorType, Integer pageNo, Integer pageSize) {
        log.info("根据用户ID和行为类型查询文章: 用户ID:{}, 行为类型:{}, 页码:{}, 每页大小:{}", userId, behaviorType, pageNo, pageSize);
        
        // 构建查询条件，查询用户行为记录
        BoolQuery.Builder boolQuery = QueryBuilders.bool();
        boolQuery.must(QueryBuilders.term(t -> t.field("behaviorUserId").value(userId)));
        boolQuery.must(QueryBuilders.term(t -> t.field("behavior").value(behaviorType)));
        
        // 构建NativeQuery
        NativeQuery nativeQuery = NativeQuery.builder()
                .withQuery(boolQuery.build()._toQuery())
                .withPageable(PageRequest.of(pageNo - 1, pageSize))
                .withSort(Sort.by(Sort.Order.desc("createTime")))
                .build();
        
        // 执行ES查询，获取用户行为记录
        SearchHits<ActionSearchPO> actionHits = elasticsearchTemplate.search(nativeQuery, ActionSearchPO.class);
        
        // 提取文章ID列表
        List<Integer> articleIds = actionHits.get().map(hit -> hit.getContent().getArticleId()).collect(Collectors.toList());
        
        if (articleIds.isEmpty()) {
            PageInfo<ArticleSearchPO> pageInfo = new PageInfo<>();
            pageInfo.setList(new ArrayList<>());
            pageInfo.setPageNum(pageNo);
            pageInfo.setPageSize(pageSize);
            pageInfo.setTotal(0L);
            pageInfo.setPages(0);
            return pageInfo;
        }
        
        // 根据文章ID列表查询文章详情
        BoolQuery.Builder articleQuery = QueryBuilders.bool();
        for (Integer articleId : articleIds) {
            articleQuery.should(QueryBuilders.term(t -> t.field("id").value(articleId)));
        }

        // 构建文章查询的NativeQuery
        NativeQuery articleNativeQuery = NativeQuery.builder()
                .withQuery(articleQuery.build()._toQuery())
                .withPageable(PageRequest.of(pageNo - 1, pageSize))
                .build();
        
        // 执行文章查询
        SearchHits<ArticleSearchPO> articleHits = elasticsearchTemplate.search(articleNativeQuery, ArticleSearchPO.class);
        
        // 转换结果
        List<ArticleSearchPO> articleList = articleHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        
        // 构建PageInfo对象
        PageInfo<ArticleSearchPO> pageInfo = new PageInfo<>();
        pageInfo.setList(articleList);
        pageInfo.setPageNum(pageNo);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotal(actionHits.getTotalHits());
        pageInfo.setPages((int) Math.ceil((double) actionHits.getTotalHits() / pageSize));
        
        return pageInfo;
    }

    @Override
    public Set<String> articleLabels(ArticleQuery articleQuery) {
        log.info("ES查询文章标签列表:{}", articleQuery);
        
        // 构建查询条件
        BoolQuery.Builder boolQuery = QueryBuilders.bool();
        
        // 添加位置查询条件 - 如果提供了经纬度，则查询附近的文章
        if (articleQuery.getLatitude() != null && articleQuery.getLongitude() != null) {
            try {
                Double lat = Double.valueOf(articleQuery.getLatitude());
                Double lon = Double.valueOf(articleQuery.getLongitude());
                
                // 使用geo_distance查询查找附近的文档
                // 假设在5公里范围内的文章
                boolQuery.filter(QueryBuilders.geoDistance(g -> g
                    .field("location")
                    .distance("5000km")
                    .location(l -> l.latlon(ll -> ll.lat(lat).lon(lon)))));
            } catch (NumberFormatException e) {
                log.warn("无效的经纬度格式: latitude={}, longitude={}", 
                         articleQuery.getLatitude(), articleQuery.getLongitude());
            }
        }
        
        // 构建NativeQuery
        NativeQuery nativeQuery = NativeQuery.builder()
                .withQuery(boolQuery.build()._toQuery())
                .build();
        
        // 执行ES查询
        SearchHits<ArticleSearchPO> searchHits = elasticsearchTemplate.search(nativeQuery, ArticleSearchPO.class);
        
        // 提取所有标签
        Set<String> labels = new HashSet<>();
        searchHits.get().forEach(hit -> {
            ArticleSearchPO article = hit.getContent();
            if (article.getArticleLabel() != null && !article.getArticleLabel().isEmpty()) {
                labels.add(article.getArticleLabel());
            }
        });
        
        log.info("查询到{}个标签", labels.size());
        return labels;
    }

}
